#include <sys/types.h>
#include <sys/socket.h>
#include <iostream>
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <string.h>

#include "Listener.hpp"
#include "error.hpp"

using namespace std;

/**
 * Listener
 **/
Listener::Listener(int port,ClientThread* clientThreads,int nbClientThreads)
{
	this->nbClientThreads=nbClientThreads;
	this->clientThreads=clientThreads;
	this->port=port;
}
void Listener::run()
{

	/**
	 * socket creation
	 * PF_INET = IPV4
	 * SOCK_STREAM = TCP
	 * 0 = default (IPPROTO_TCP)
	 * --> man 7 ip
	 **/ 
	this->sfd=socket(PF_INET,SOCK_STREAM,0);
	if(sfd<0)
		error((char*)"socket error");
	else
		cout << "socket : OK " << endl;

	/* set sock opt reuse address */
	int i=1;
	if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0)
		error((char*)"SETSOCKOPT ERROR ");



	/* set sock option no delay */
         if(setsockopt(sfd,IPPROTO_TCP,TCP_NODELAY,(char*)&i,sizeof(i)))
		error((char*)"SETSOCKOPT_ERROR #2");



	/* bind the sock */

        /* sockaddr_in */
	struct sockaddr_in sa;
	sa.sin_family=AF_INET;
	sa.sin_port=htons(port);
	sa.sin_addr.s_addr=htonl(INADDR_ANY);

        if(bind(sfd,(struct sockaddr*)&sa,sizeof(sa)))
		error((char*)"bind error");
	else
		cout << "bind : OK" << endl;
		
	/* listen  ( socket file descriptor , queue ) */
	if(listen(sfd,255))
		error((char*)"listen error");
	else
		cout << "listen : OK" << endl;

	
	int newSock;
	char buffer[1025];
	int size;

	/* accept loop */
	while('a')
	{
		if((newSock=accept(sfd,NULL,NULL))<0)
			error((char*)"accept error");

		/* recv hello || policy-file-request */
		if((size=recv(newSock,buffer,1024,0))>-1)
		{
			/* add char* end */
			buffer[size]=0;
			if(!strcmp("<policy-file-request/>",buffer))
			{
				/* send policy and close */
				char* policy=(char*)" <?xml version=\"1.0\"?> <!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\"> <cross-domain-policy> <allow-access-from domain=\"*\" to-ports=\"*\"/> </cross-domain-policy>";
				if((send(newSock,policy,strlen(policy),0))<10)
					error((char*)"send policy");
				close(newSock);
				continue;
			}
//			if(!strcmp("<hello/>",buffer))
			else
			{
				int i;

				/* new client connected */
				cout << "new client sfd = " << newSock << endl;
				send(newSock,"connected",9,0);
				
				/* dispatch connection */
				i=0;
				while(i<this->nbClientThreads)
				{
					if(this->clientThreads[i].addClient(newSock))
						break;
					++i;
				}

				/* error */
				if(i==this->nbClientThreads)
				{
					error((char*)"can't add new client\n");
					close(newSock);
				}
				else
				{
			//		cout << "OK1\n";
				}
			}
		}
		else
		{
			cout << "problem\n";
			if(size==-1)
				error((char*)"recv error");
			else
			{/* disconnection */}
		}
	}
}

